Photo by Sébastien Goldberg on Unsplash
Mount Cook, Nouvelle-Zélande
期望實作這功能
RatingView 子視圖會告訴父視圖,Rating 給幾顆星⭐️。
發現之前招式
struct PublicSwimmingPoolDetailView: View {
var publicSwimmingPool: PoolItem
}
// ------
PublicSwimmingPoolDetailView(publicSwimmingPool: item)
publicSwimmingPool 是 read-only property 🤔
研究一陣子開竅,需要 @Binding 新招式
@State
用於私有狀態管理。
主要用於視圖內部,當狀態變化時,視圖會重新渲染。
是值類型的存儲方式,當值改變時,只有與該值有關的視圖部分會被重新渲染。
例子:
@State private var isToggled: Bool = false
@Binding
這是一種參照某個其它狀態的方式。當你需要從一個視圖到另一個視圖共享同一狀態時,這非常有用。
它不擁有該狀態的真實存儲,而是提供一種方式來讀取和寫入該值。
例子:
@Binding var text: String
read-only property
struct ParentView: View {
@State private var pool = PoolItem(name: "Community Pool")
var body: some View {
VStack {
// ... 其他 UI ...
PublicSwimmingPoolDetailView(publicSwimmingPool: pool)
}
}
}
struct PublicSwimmingPoolDetailView: View {
var publicSwimmingPool: PoolItem
var body: some View {
// ... 使用 publicSwimmingPool ...
}
}
視覺化解釋
struct RatingView: View {
@Binding var rating: Int
var label = ""
var maximumRating = 5
var offImage: Image?
var onImage = Image(systemName: "star.fill")
var offColor = Color.gray
var onColor = Color.yellow
var body: some View {
HStack {
if label.isEmpty == false {
Text(label)
}
ForEach(1..<maximumRating + 1, id: \.self) { number in
image(for: number)
.resizable()
.scaledToFit()
.frame(width: 28, height: 28)
.foregroundColor(number > rating ? offColor : onColor)
.onTapGesture {
rating = number
}
}
}
}
func image(for number: Int) -> Image {
if number > rating {
return offImage ?? onImage
} else {
return onImage
}
}
}
明天介紹 @ViewBuilder,接續做 FeedBack 功能
下集待續